package unit

import (
	"context"
	"os"
	"time"

	"github.com/starter-go/application"
	"github.com/starter-go/mails"
	"github.com/starter-go/starter"
)

// ModuleGroup   ...  由 main 函数传入的一组模块
type ModuleGroup struct {
	Server     application.Module
	Driver     application.Module
	Agent      application.Module
	Dispatcher application.Module
}

// TestDriverAgentServerDispatcher ...
type TestDriverAgentServerDispatcher struct {

	//starter:component

	AppContext application.Context //starter:inject("context")
	Sender     mails.Service       //starter:inject("#")

	ToAddr string //starter:inject("${mails.test.to-address}")

}

// Life ...
func (inst *TestDriverAgentServerDispatcher) Life() *application.Life {
	return &application.Life{
		OnStart: inst.start,
		OnLoop:  inst.loop,
	}
}

// GetModules ...
func (inst *TestDriverAgentServerDispatcher) GetModules() *ModuleGroup {

	atts := inst.AppContext.GetAttributes()
	obj, err := atts.GetAttributeRequired("pnp.modules")
	if err != nil {
		panic(err)
	}
	return obj.(*ModuleGroup)
}

func (inst *TestDriverAgentServerDispatcher) loop() error {
	for {
		time.Sleep(time.Second)
	}
}

func (inst *TestDriverAgentServerDispatcher) start() error {

	mods := inst.GetModules()

	inst.startSubModule(mods.Server, 0)
	inst.startSubModule(mods.Dispatcher, 3*time.Second)

	time.Sleep(5 * time.Second)
	return inst.sendTestMail()
}

func (inst *TestDriverAgentServerDispatcher) startSubModule(m application.Module, delay time.Duration) error {
	go func() {
		err := inst.runSubModule(m, delay)
		if err != nil {
			panic(err)
		}
	}()
	return nil
}

func (inst *TestDriverAgentServerDispatcher) runSubModule(m application.Module, delay time.Duration) error {

	time.Sleep(delay)

	args := os.Args
	i := starter.Init(args)
	i.MainModule(m)
	i.WithPanic(false)
	return i.Run()
}

func (inst *TestDriverAgentServerDispatcher) sendTestMail() error {

	ctx := context.Background()
	content := "hello, mail text"
	to := mails.Address(inst.ToAddr)

	msg := &mails.Message{
		Title:       "hello",
		FromAddress: "",
		ToAddresses: []mails.Address{to},
		ContentType: "text/plain",
		Content:     []byte(content),
	}

	return inst.Sender.Send(ctx, msg)
}
